package org.monitor.servlet.base;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.monitor.http.RestResult;
import org.monitor.kit.FileKit;
import org.monitor.servlet.controller.Controller;
import org.monitor.servlet.pairs.PairsBuilder;
import org.monitor.servlet.router.Action;
import org.monitor.servlet.router.ActionMappings;
import org.monitor.servlet.router.Routers;

import com.google.gson.Gson;

public abstract class BaseHttpServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	
	protected ActionMappings actionMappings;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		Routers routers = initRouters();
		actionMappings = routers.build();
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Resource resource = getResource(req);
		resp.setCharacterEncoding("UTF-8");

		boolean find = false;
		if(actionMappings != null){
			Action action = actionMappings.getAction(resource);
			if(action != null){
				find = true;
				PairsBuilder builder = getPairsBuilder(req);
				RestResult rst = null;
				try {
					Controller controller = action.getController().newInstance();
					controller.init(req, resp, resource, builder.build());
					
					action.getMethod().invoke(controller);
					
				}catch(Exception e){
					rst = new RestResult();
					rst.setState(-1);
					if(e.getCause() != null){
						rst.setMsg(e.getCause().getMessage());
					}
					
					resp.setHeader("Content-type", "text/plain;charset=UTF-8");
					Gson gson = new Gson();
					resp.getWriter().write(gson.toJson(rst));
				}
			}
		}
		if(!find){
			resp.setCharacterEncoding("UTF-8");
			resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Resource ["+resource.getResource()+"] is not found!");
		}
	}

	protected Resource getResource(HttpServletRequest req){
		Resource action = new Resource();
		action.setMethod(req.getMethod());
		String ctxPath = req.getServletContext().getContextPath();
		String resource = req.getRequestURI().replaceFirst(ctxPath, "").replaceFirst(req.getServletPath(), "");
		if("".equals(resource)){
			resource = "/";
		}
		action.setResource(resource);
		return action;
	}

	protected PairsBuilder getPairsBuilder(HttpServletRequest req) {
		PairsBuilder builder = PairsBuilder.create();
		Enumeration<String> enums = req.getParameterNames();
		while(enums.hasMoreElements()){
			String name = enums.nextElement();
			builder.addPair(name, req.getParameter(name));
		}
		builder.setPostData(getPostData(req));
		return builder;
	}

	protected byte[] getPostData(HttpServletRequest req) {
		byte[] postData = null;
		InputStream is = null;
		try {
			is = req.getInputStream();
			postData = FileKit.read(is);
		} catch (IOException e) {
		}finally {
			FileKit.close(is);
		}
		
		return postData;
	}

	protected abstract Routers initRouters();
}
